Regular expressions
Cyclone has an interface to the [Perl Compatible Regular Expressions][1] (PCRE) library.
Here’s a Perl program that does a simple substitution:
my $x = "Hello, Bob";
$x =~ s/Bob/World/;
print $x, "\n";
It prints “Hello, World.” The equivalent Cyclone program is
#include <stdio.h>
#include <pcre.h>
int main() {
let x = "Hello, Bob";
let y = pcre_s(x,"Bob","World",0);
printf("%s\n",y);
return 0;
}
You need to compile this program with the -lpcre
flag.
A global replacement, like the Perl s/foo/bar/g
, is done with
y = pcre_s_g(x,"foo","bar",0);
The last argument of pcre_s
and pcre_s_g
allows you to set
options for the substitution. For example the Perl
s/(foo|bar)baz/$1/gms
corresponds to
y = pcre_s_g(x,"(foo|bar)baz","$1",PCRE_MULTILINE|PCRE_DOTALL);
The options you can pass this way are PCRE_MULTILINE
(for m
),
PCRE_DOTALL
(for s
), PCRE_CASELESS
(for i
), and
PCRE_EXTENDED
(for x
).
The Perl option e
allows you to execute Perl statements at each
match in the substitution, for example,
s{([A-Z]+)}{lc($1)}e
matches every word in upper case only, and converts that text to lower
case using the function lc
. The result of the evaluation should be
a string that is the replacement value.
The equivalent in Cyclone would be
y = PCRE_S_EG(x,"([A-Z]+)",
({ let one = DOLLAR(1);
STRING(lc(one)); }),
0);
PCRE_S_EG
is a macro. The third argument of the macro is an
expression to be executed at each match. Here, we have used a
statement expression, which allows us to use declarations, etc.
The macro DOLLAR
returns a new, heap-allocated copy of the
corresponding match (so DOLLAR(1)
is like $1
in Perl). The macro
STRING
adds its argument to the replacement text.